﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MathNet.Numerics.LinearAlgebra.Double;

namespace MoveView.MyMath
{
    public class ModelViewCalc
    {
        private DoubleDenseVector3D camPos { get; set; }
        private DoubleDenseVector3D camTarget { get; set; }
        private DoubleDenseVector3D camUp { get; set; }


        private DenseMatrix privMatrix = new DenseMatrix(4,4);

        public ModelViewCalc(   double eyeX,    double eyeY,    double eyeZ, 
                                double centerX, double centerY, double centerZ,
                                double upX,     double upY,     double upZ)
        {
            camPos = new DoubleDenseVector3D(eyeX, eyeY, eyeZ);
            camTarget = new DoubleDenseVector3D(centerX, centerY, centerZ);
            camUp = new DoubleDenseVector3D(upX, upY, upZ);
            getMatrix(new DoubleDenseVector3D(camPos));
        }

        public double[,] getMatrix( double eyeX,    double eyeY,    double eyeZ, 
                                    double centerX, double centerY, double centerZ,
                                    double upX,     double upY,     double upZ,
                                    double translateX, double translateY, double translateZ)
        {
            camPos = new DoubleDenseVector3D(eyeX,eyeY,eyeZ);
            camTarget = new DoubleDenseVector3D(centerX,centerY,centerZ);
            camUp = new DoubleDenseVector3D(upX, upY, upZ);
            var translate = new DoubleDenseVector3D(translateX, translateY, translateZ);
            return getMatrix(translate);
        }
        
        public bool compare(DoubleDenseVector3D pos, DoubleDenseVector3D up, DoubleDenseVector3D tar)
        {
            return (pos == camPos && up == camUp && tar == camTarget);
        }

        private double[,] getMatrix( DoubleDenseVector3D translate)
        {
            var translation = translate;
            DoubleDenseVector3D forward = new DoubleDenseVector3D(camTarget - camPos);     
            forward = forward.Normalize();
            
            DoubleDenseVector3D left = camUp.CrossProduct(forward);
            left = left.Normalize();

            DoubleDenseVector3D up = forward.CrossProduct(left);
            up = up.Normalize();

            double[] leftArr = new double[4];
            left.ToArray().CopyTo(leftArr, 0);
            double[] upArr = new double[4];
            up.ToArray().CopyTo(upArr, 0);
            double[] forwardArr = new double[4];
            forward.ToArray().CopyTo(forwardArr, 0);
            double[] translateArr = new double[4];
            translate.ToArray().CopyTo(translateArr, 0);

            privMatrix.SetRow(0, leftArr);
            privMatrix.SetRow(1, upArr);
            privMatrix.SetRow(2, forwardArr);
            privMatrix.SetRow(3, translateArr);
            privMatrix[3, 3] = 1;

            //Console.WriteLine(privMatrix.ToMatrixString(4,4));

            return privMatrix.ToArray();
        }

        public DoubleDenseVector3D CalcGlobalCoordinates(double x, double y, double z)
        {
            DenseVector localCoord = new DenseVector(new double[]{x,y,z,0});
            DenseVector globalCoord = new DenseVector(4);

            globalCoord = privMatrix.TransposeThisAndMultiply(localCoord) as DenseVector;

            DoubleDenseVector3D resultVector = new DoubleDenseVector3D(globalCoord);
            return resultVector;
        }
    }
}
